﻿import kliment.math.Calc;
import kliment.geom.color.*;

/**
 * ...
 * @author	Kliment
 * @version	1.0.0
 */
class kliment.geom.color.XYZColor extends ColorAbstract {
	public var rawX:Number = 0;
	public var rawY:Number = 0;
	public var rawZ:Number = 0;
	
	function XYZColor(host:Color) {
		super(host);
	}
	
	public function get x():Number { return (rawX * 1000 + 0.499999 << 0) / 1000 }
	public function get y():Number { return (rawY * 1000 + 0.499999 << 0) / 1000 }
	public function get z():Number { return (rawZ * 1000 + 0.499999 << 0) / 1000 }
	
	public function setValue(x:Number, y:Number, z:Number, update:Boolean):Void {
		setValue(x, y, z, update);
	}
	
	public function setRawValue(x:Number, y:Number, z:Number, update:Boolean):Void {
		if (update == undefined) update = true;
		if (rawX == x && rawY == y && rawZ == z)
			return;
		
		rawX = Calc.inInterval(MIN_RAW, MAX_RAW, x);
		rawY = Calc.inInterval(MIN_RAW, MAX_RAW, y);
		rawZ = Calc.inInterval(MIN_RAW, MAX_RAW, z);
		
		if (color && update)
			color.valueChanged(Color.XYZ);
	}
	
	public function toString():String {
		return "[XYZColor x=" + x + " y=" + y + " z=" + z + "]";
	}
	
	public function clone():XYZColor {
		var result:XYZColor = new XYZColor();
		result.setRawValue(rawX, rawY, rawZ, false);
		return result;
	}
	
	public function toLAB(lab:LABColor):LABColor { return converToLAB(this, lab) }
	
	static public function converToLAB(xyz:XYZColor, lab:LABColor ):LABColor {
		if (!lab) lab = new LABColor();
		
		var x:Number = xyz.rawX;
		var y:Number = xyz.rawY;
		var z:Number = xyz.rawZ;
		var l:Number = x > .008856 ? (Math.pow(x, 1 / 3)) : (7.787 * x + .1379);
		var a:Number = y > .008856 ? (Math.pow(y, 1 / 3)) : (7.787 * y + .1379);
		var b:Number = z > .008856 ? (Math.pow(z, 1 / 3)) : (7.787 * z + .1379);
		lab.setValue(116 * a - 16, 500 * (l - a), 200 * (a - b), false);
		return lab;
	}
	
	public function toRGB(rgb:RGBColor ):RGBColor { return converToRGB(this, rgb) }
	static public function converToRGB(xyz:XYZColor, rgb:RGBColor):RGBColor {
		if (!rgb) rgb = new RGBColor();
		
		var rawX:Number = xyz.rawX;
		var rawY:Number = xyz.rawY;
		var rawZ:Number = xyz.rawZ;
		rawX = rawX * (95.047 / 100);
		rawZ = rawZ * (108.883 / 100);
		var rawR:Number = 3.24063 * rawX - 1.53721 * rawY - .498629 * rawZ;
		var rawG:Number = -.968931 * rawX + 1.87576 * rawY + .0415175 * rawZ;
		var rawB:Number = 0.0557101 * rawX - .204021 * rawY + 1.057 * rawZ;
		rawR = (rawR > .0031308)?(1.055 * Math.pow(rawR, .4167) - .055):(12.92 * rawR);
		rawG = (rawG > .0031308)?(1.055 * Math.pow(rawG, .4167) - .055):(12.92 * rawG);
		rawB = (rawB > .0031308)?(1.055 * Math.pow(rawB, .4167) - .055):(12.92 * rawB);
		rgb.setRawValue(rawR, rawG, rawB, false);
		
		return rgb;
	}
}
